package com.sh4.util;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.Random;
import java.util.Set;
import java.util.TimeZone;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

import javax.servlet.http.HttpServletRequest;

import org.springframework.web.multipart.MultipartFile;

import com.sh4.util.wechatUtils.Core;

import net.sf.json.JSONObject;

public class Sh4Utils {
	/***
	 * 路径分隔符
	 */
	private  static String separator = File.separator;
	
	/***
	 * 文件存储根路径
	 */
	private static String rootDirName = "files";
	/***
	 * 文件存储文件夹
	 */
	private static String fileDirName = "file";
	/***
	 * 新赣防水服务号appid
	 */
	private static String wxAppId = "wxdc5a29a515e9ed92";
	/***
	 * 项目所在位值
	 */
	private static String rootUrl = "http://www.xgfsgc.com/WsM"; 
	/***
	 * 新赣防水 服务号秘钥
	 */
	private static String appSecret = "02a6cb4d7516f1f338ec993f0e5ea2a0";
	
	/***
	 * 新赣防水服务号token
	 */
	private static String token = "xgfs";
	
	/***
	 * 新赣防水 access_token
	 */
	private static String access_token = null;
	
	/***
	 * 新赣防水access_token过期时间
	 */
	private static Date access_token_ctreate_date = null;
	/***
	 * 新赣防水最新 access_token 可持续使用时间
	 */
	private static int expires_in = 0;
	
	private static Logger log = Logger.getLogger("Sh4Utils");
	
	public static final String[] zodiacArr = { "猴", "鸡", "狗", "猪", "鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊" };

	public static final String[] constellationArr = { "水瓶座", "双鱼座", "白羊座", "金牛座", "双子座", "巨蟹座", "狮子座", "处女座", "天秤座",
			"天蝎座", "射手座", "魔羯座" };

	public static final int[] constellationEdgeDay = { 20, 19, 21, 21, 21, 22, 23, 23, 23, 23, 22, 22 };
	
	public static String getProjetRootPath(){
		
		String classpath = Sh4Utils.class.getClassLoader().getResource("/").getPath();
		
		log.info(classpath);
		
		int index = classpath.indexOf("wtpwebapps");
		
		if(index == -1) {
			index = classpath.indexOf("webapps");
		}
		
		String webappPath = classpath.substring(0, index);
		log.info(webappPath+"webapps");
		
		return webappPath+"webapps";
	}
	
	/***
	 * 格式化时间 
	 * @return 字符串
	 */
	public static String getDateStr(){
		
		Date current = new Date();
		SimpleDateFormat format  = new SimpleDateFormat("yyyyMMdd");
		
		return format.format(current);
	}
	
	/***
	 * 保存图片到本地对应位置
	 * @param file
	 * @param request
	 * @return
	 * @throws IllegalStateException
	 * @throws IOException
	 */
	public static JSONObject saveImageFile2Disk(MultipartFile file , HttpServletRequest request) throws IllegalStateException, IOException{
		
		JSONObject result = new JSONObject();
		//获取项目所在的webapps的路径
		String path = getProjetRootPath();
				
		//创建文件夹
		File folder = new File(path + request.getContextPath() + rootDirName + separator  + fileDirName + separator + Sh4Utils.getDateStr());
		
		//文件重新命名
		String reName = System.currentTimeMillis()+"";
		
		int index = file.getOriginalFilename().indexOf(".");
		
		String suffix = file.getOriginalFilename().substring(index);
		
		String filePth = folder+separator+reName + suffix;
		
		int webappsIndex = filePth.indexOf("webapps");
		
		if(webappsIndex == -1) {
			webappsIndex = filePth.indexOf("wptwebapps");
		}
		
		File f = new File(filePth);
		
		//判断文件夹是否存在 不存在创建
		if(!f.exists()){
			f.mkdirs();
		}
		file.transferTo(f);
		
		String httpUrl = request.getRequestURL()+"";
		
//		httpUrl = httpUrl.replace(request.getRequestURI(), "");
//		httpUrl = filePth.replace(path, httpUrl);
		httpUrl = filePth.substring(webappsIndex);
		
		if(httpUrl.indexOf("webapps") > -1) {
			httpUrl = httpUrl.replace("webapps", "");
		}else if(httpUrl.indexOf("wtpwebapps") > -1) {
			httpUrl = httpUrl.replace("wtpwebapps", "");
		}
		
		result.put("httpUrl", httpUrl);
		result.put("localPath", filePth);
		
		return result;
	}
	
	/**
	 * 密码加密
	 */
	public static String getSha1(String str){
        if(str==null||str.length()==0){
            return null;
        }
        char hexDigits[] = {'0','1','2','3','4','5','6','7','8','9',
                'a','b','c','d','e','f'};
        try {
            MessageDigest mdTemp = MessageDigest.getInstance("SHA1");
            mdTemp.update(str.getBytes("UTF-8"));

            byte[] md = mdTemp.digest();
            int j = md.length;
            char buf[] = new char[j*2];
            int k = 0;
            for (int i = 0; i < j; i++) {
                byte byte0 = md[i];
                buf[k++] = hexDigits[byte0 >>> 4 & 0xf];
                buf[k++] = hexDigits[byte0 & 0xf];      
            }
            return new String(buf);
        } catch (Exception e) {
            return null;
        }
    }
	

	/**
	 * 判断 权限
	 * @param authority
	 * @return
	 */
	public static boolean chackAuthority(String fromAuthority,String toAuthority){
		return Integer.parseInt("fromAuthority")<=Integer.parseInt("toAuthority");
	}
	/**
	 * 校验密码格式
	 * @param password
	 * @return
	 */
	public static boolean chackPassword(String password) {
		// System.out.println(password.matches("[A-Za-z0-9_]+"));
		return password.matches("\\w+");
	}
	 /**
	  * 右补位，左对齐
	  * @param oriStr  原字符串
	  * @param len  目标字符串长度
	  * @param alexin  补位字符
	  * @return  目标字符串
	  */
	 public static String padRight(String oriStr,int len,int alexin){
	  int strlen = oriStr.length();
	  String str = "";
	  if(strlen < len){
	   for(int i=0;i<len-strlen;i++){
	    str = str+alexin;
	   }
	  }
	  str = str + oriStr;
	  return str;
	 }
	 /**
	  * 左补位，右对齐
	  * @param oriStr  原字符串
	  * @param len  目标字符串长度
	  * @param alexin  补位字符
	  * @return  目标字符串
	  */
	 public static String padLeft(String oriStr,int len,int alexin){
	  int strlen = oriStr.length();
	  String str = "";
	  if(strlen < len){
	   for(int i=0;i<len-strlen;i++){
	    str = str+alexin;
	   }
	  }
	  str = oriStr + str;
	  return str;
	 }
	/**
	 * 判断 两天之间 查多少秒
	 * 
	 * @param startDate
	 * @param endDate
	 * @return
	 * @throws ParseException
	 */
	public static long getCompareDate(String startDate, String endDate) throws ParseException {
		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
		Date date1 = formatter.parse(startDate);
		Date date2 = formatter.parse(endDate);
		long l = date2.getTime() - date1.getTime();
		long d = l / (1000);
		return d;
	}



	/**
	 * 判断 字符串 是否 是时间格式 2017-05-24
	 * 
	 * @param time
	 * @return
	 */
	public static boolean TimeByBirthday(String time) {
		return time.matches("\\d{4}-\\d{2}-\\d{2}");
		// || time.matches("\\d{4}-\\d{2}-\\d{2}");
	}

	/**
	 * 判断 字符串 是否 是时间格式 2017-05-24 12:30
	 * 
	 * @param time
	 * @return
	 */
	public static boolean TimeByFormat(String time) {
		return time.matches("\\d{4}-\\d{2}-\\d{2}\\s\\d{2}:\\d{2}");
		// || time.matches("\\d{4}-\\d{2}-\\d{2}");
	}

	/**
	 * 大陆号码或香港号码均可
	 */
	public static boolean isPhoneLegal(String str) throws PatternSyntaxException {
		return isChinaPhoneLegal(str) || isHKPhoneLegal(str);
	}

	/**
	 * 大陆手机号码11位数，匹配格式：前三位固定格式+后8位任意数 此方法中前三位格式有： 13+任意数 15+除4的任意数 18+除1和4的任意数
	 * 17+除9的任意数 147
	 */
	public static boolean isChinaPhoneLegal(String str) throws PatternSyntaxException {
		String regExp = "^((13[0-9])|(15[^4])|(18[0,2,3,5-9])|(17[0-8])|(147))\\d{8}$";
		Pattern p = Pattern.compile(regExp);
		Matcher m = p.matcher(str);
		return m.matches();
	}

	/**
	 * 香港手机号码8位数，5|6|8|9开头+7位任意数
	 */
	public static boolean isHKPhoneLegal(String str) throws PatternSyntaxException {
		String regExp = "^(5|6|8|9)\\d{7}$";
		Pattern p = Pattern.compile(regExp);
		Matcher m = p.matcher(str);
		return m.matches();
	}

	/**
	 * 获得电话号码的正则表达式：包括固定电话和移动电话 符合规则的号码： 1》、移动电话 86+‘-’+11位电话号码 86+11位正常的电话号码
	 * 11位正常电话号码a (+86) + 11位电话号码 (86) + 11位电话号码 2》、固定电话 区号 + ‘-’ + 固定电话 + ‘-’ +
	 * 分机号 区号 + ‘-’ + 固定电话 区号 + 固定电话
	 * 
	 * @return 电话号码的正则表达式
	 */
	public static String isPhoneRegexp() {
		String regexp = "";

		// 能满足最长匹配，但无法完成国家区域号和电话号码之间有空格的情况
		String mobilePhoneRegexp = "(?:(\\(\\+?86\\))((13[0-9]{1})|(15[0-9]{1})|(18[0,5-9]{1}))+\\d{8})|"
				+ "(?:86-?((13[0-9]{1})|(15[0-9]{1})|(18[0,5-9]{1}))+\\d{8})|"
				+ "(?:((13[0-9]{1})|(15[0-9]{1})|(18[0,5-9]{1}))+\\d{8})";
		// System.out.println("regexp = " + mobilePhoneRegexp);
		// 固定电话正则表达式

		String landlinePhoneRegexp = "(?:(\\(\\+?86\\))(0[0-9]{2,3}\\-?)?([2-9][0-9]{6,7})+(\\-[0-9]{1,4})?)|"
				+ "(?:(86-?)?(0[0-9]{2,3}\\-?)?([2-9][0-9]{6,7})+(\\-[0-9]{1,4})?)";

		regexp += "(?:" + mobilePhoneRegexp + "|" + landlinePhoneRegexp + ")";

		return regexp;
	}

	/**
	 * 从dataStr中获取出所有的电话号码（固话和移动电话），将其放入Set
	 * 
	 * @param dataStr
	 *            待查找的字符串
	 * @param phoneSet
	 *            dataStr中的电话号码
	 */
	public static void getPhoneNumFromStrIntoSet(String dataStr, Set<String> phoneSet) {
		// 获得固定电话和移动电话的正则表达式
		String regexp = isPhoneRegexp();

		System.out.println("Regexp = " + regexp);

		Pattern pattern = Pattern.compile(regexp);
		Matcher matcher = pattern.matcher(dataStr);

		// 找与该模式匹配的输入序列的下一个子序列
		while (matcher.find()) {
			// 获取到之前查找到的字符串，并将其添加入set中
			phoneSet.add(matcher.group());
		}
		// System.out.println(phoneSet);
	}

	/**
	 * 根据日期获取生肖
	 * 
	 * @return
	 */
	public static String getZodica(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		return zodiacArr[cal.get(Calendar.YEAR) % 12];
	}

	/**
	 * 根据日期获取星座
	 * 
	 * @return
	 */
	public static String getConstellation(Date date) {
		if (date == null) {
			return "";
		}
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		int month = cal.get(Calendar.MONTH);
		int day = cal.get(Calendar.DAY_OF_MONTH);
		if (day < constellationEdgeDay[month]) {
			month = month - 1;
		}
		if (month >= 0) {
			return constellationArr[month];
		}
		return constellationArr[11];
	}

	/**
	 * 根据日期计算年龄
	 */
	public static int getAge(Date date) {

		if (date == null)
			throw new RuntimeException("出生日期不能为null");
		int age = 0;
		Date now = new Date();
		SimpleDateFormat format_y = new SimpleDateFormat("yyyy");
		SimpleDateFormat format_M = new SimpleDateFormat("MM");
		String birth_year = format_y.format(date);
		String this_year = format_y.format(now);
		String birth_month = format_M.format(date);
		String this_month = format_M.format(now);
		// 初步，估算
		age = Integer.parseInt(this_year) - Integer.parseInt(birth_year);
		// 如果未到出生月份，则age - 1
		if (this_month.compareTo(birth_month) < 0)
			age -= 1;
		if (age < 0)
			age = 0;
		return age;
	}


	/**
	 * 时间格式修改
	 * 
	 * @param key
	 * @return
	 */
	public static Date getTime(String str) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:MM:SS");
		java.sql.Date sdate = null; // 初始化
		Date udate = null;
		try {
			udate = sdf.parse(str);
			sdate = new java.sql.Date(udate.getTime()); // 2013-01-14
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return sdate;
	}

	/**
	 * 获得相差时间
	 * 
	 * @param key
	 * @return
	 */
	public static String getTimeString(Date nowdate, Date date) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); // 文本转换成日期
		Long dateLg = date.getTime();
		Long nowdateLg = nowdate.getTime();
		String result = "";

		Long difference = (nowdateLg - dateLg) / (1000 * 60); // 相差分钟数

		if (difference < 60) {
			result = difference + "分钟前";
		} else {
			difference = difference / 60; // 相差小时数
			if (difference < 24) {
				result = difference + "小时前";
			} else {
				difference = difference / 24; // 相差天数
				if (difference < 7) { // 超过7天显示日期
					result = difference + "天前";
				} else {
					result = sdf.format(date);
				}
			}
		}
		return result;
	}

	/**
	 * 报错信息
	 */
	public static String error(String txt) {
		String html = "<html><body style=\"background: url('http://weixin1.kmtsolution.com/clothesNew/error.jpg') no-repeat;\"><div style=\"text-align: center;margin:930px 100px 30px 100px; color: gray;\"><h1>"
				+ changeUTF8(txt) + "</h1></div></body></body></html>";
		return html;
	}

	/**
	 * 产生随机的六位数
	 * 
	 * @return
	 */
	public static String getFive() {
		Random rad = new Random();
		String result = rad.nextInt(1000000) + "";
		if (result.length() != 5) {
			return getFive();
		}
		return result;
	}

	/**
	 * 获取当前时间戳
	 * 
	 * @param
	 * @return
	 */
	public static long getTime() {
		long a = System.currentTimeMillis() / 1000;
		return a;
	}

	/**
	 * 获取当前时间戳
	 * 
	 * @param
	 * @return
	 */
	public static Timestamp getTimestamp() {
		Timestamp d = new Timestamp(System.currentTimeMillis());
		return d;
	}

	/**
	 * 将时间戳(分)转换为时间
	 */
	public static String stampToDate(String s) {
		// 关注时间戳
		Long subscribeTime = Long.parseLong(s);
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String date = sdf.format(new Date(subscribeTime * 1000L));
		return date;
	}

	/**
	 * 将时间戳(分)转换为时间
	 */
	public static String stampToDate2(String s) {
		// 关注时间戳
		Long subscribeTime = Long.parseLong(s);
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		String date = sdf.format(new Date(subscribeTime));
		return date;
	}

	/**
	 * 时间戳转 UTC
	 */
	public static String getDateString(Long CreateTime) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTimeInMillis(CreateTime);
		calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
		return calendar.getTime().toString();
	}

	/**
	 * 解决中文乱码问题
	 * 
	 * @param key
	 * @return
	 */
	public static String changeUTF8(String key) {
		String name = "";
		try {
			if (key != null) {
				name = new String(key.getBytes("ISO8859-1"), "UTF-8");
			} else {
				return null;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return name;
	}

	/**
	 * 
	 * @param plainText
	 *            明文
	 * @return 32位密文
	 */
	public static String encryption(String plainText) {
		String re_md5 = new String();
		try {
			MessageDigest md = MessageDigest.getInstance("MD5");
			md.update(plainText.getBytes());
			byte b[] = md.digest();

			int i;

			StringBuffer buf = new StringBuffer("");
			for (int offset = 0; offset < b.length; offset++) {
				i = b[offset];
				if (i < 0)
					i += 256;
				if (i < 16)
					buf.append("0");
				buf.append(Integer.toHexString(i));
			}
			re_md5 = buf.toString();

		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		return re_md5;
	}

	/**
	 * urlEncode处理
	 * 
	 * @throws UnsupportedEncodingException
	 */
	public static String urlEncode(String str) {
		String urlStr = null;
		try {
			urlStr = java.net.URLEncoder.encode(str, "GBK");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return urlStr;
	}

	/**
	 * 计算采用utf-8编码方式时字符串所占字节数
	 * 
	 * @param content
	 * @return
	 */
	public static int getByteSize(String content) {
		int size = 0;
		if (null != content) {
			try {
				// 汉字采用utf-8编码时占3个字节
				size = content.getBytes("utf-8").length;
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		}
		return size;
	}

	/**
	 * 判断是否是QQ表情
	 * 
	 * @param content
	 * @return
	 */
	public static boolean isQqFace(String content) {
		boolean result = false;

		// 判断QQ表情的正则表达式
		String qqfaceRegex = "/::\\)|/::~|/::B|/::\\||/:8-\\)|/::<|/::$|/::X|/::Z|/::'\\(|/::-\\||/::@|/::P|/::D|/::O|/::\\(|/::\\+|/:--b|/::Q|/::T|/:,@P|/:,@-D|/::d|/:,@o|/::g|/:\\|-\\)|/::!|/::L|/::>|/::,@|/:,@f|/::-S|/:\\?|/:,@x|/:,@@|/::8|/:,@!|/:!!!|/:xx|/:bye|/:wipe|/:dig|/:handclap|/:&-\\(|/:B-\\)|/:<@|/:@>|/::-O|/:>-\\||/:P-\\(|/::'\\||/:X-\\)|/::\\*|/:@x|/:8\\*|/:pd|/:<W>|/:beer|/:basketb|/:oo|/:coffee|/:eat|/:pig|/:rose|/:fade|/:showlove|/:heart|/:break|/:cake|/:li|/:bome|/:kn|/:footb|/:ladybug|/:shit|/:moon|/:sun|/:gift|/:hug|/:strong|/:weak|/:share|/:v|/:@\\)|/:jj|/:@@|/:bad|/:lvu|/:no|/:ok|/:love|/:<L>|/:jump|/:shake|/:<O>|/:circle|/:kotow|/:turn|/:skip|/:oY|/:#-0|/:hiphot|/:kiss|/:<&|/:&>";
		Pattern p = Pattern.compile(qqfaceRegex);
		Matcher m = p.matcher(content);
		if (m.matches()) {
			result = true;
		}
		return result;
	}

	/**
	 * emoji表情转换(hex -> utf-16)
	 * 
	 * @param hexEmoji
	 * @return
	 */
	public static String emoji(int hexEmoji) {
		return String.valueOf(Character.toChars(hexEmoji));
	}
	
	 /**
     * 验证签名
     *
     * @param signature
     * @param timestamp
     * @param nonce
     * @return
     */
    public static boolean checkSignature(String signature,String token, String timestamp, String nonce) {
        String[] arr = new String[] { token, timestamp, nonce };
        // 将token、timestamp、nonce三个参数进行字典序排序
        Arrays.sort(arr);
        StringBuilder content = new StringBuilder();
        for (int i = 0; i < arr.length; i++) {
            content.append(arr[i]);
        }
        MessageDigest md = null;
        String tmpStr = null;

        try {
            md = MessageDigest.getInstance("SHA-1");
            // 将三个参数字符串拼接成一个字符串进行sha1加密
            byte[] digest = md.digest(content.toString().getBytes());
            tmpStr = byteToStr(digest);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }

        content = null;
        // 将sha1加密后的字符串可与signature对比，标识该请求来源于微信
        return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false;
    }
    
    /**
     * 将字节数组转换为十六进制字符串
     *
     * @param byteArray
     * @return
     */
    private static String byteToStr(byte[] byteArray) {
        String strDigest = "";
        for (int i = 0; i < byteArray.length; i++) {
            strDigest += byteToHexStr(byteArray[i]);
        }
        return strDigest;
    }

    /**
     * 将字节转换为十六进制字符串
     *
     * @param mByte
     * @return
     */
    private static String byteToHexStr(byte mByte) {
        char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
        char[] tempArr = new char[2];
        tempArr[0] = Digit[(mByte >>> 4) & 0X0F];
        tempArr[1] = Digit[mByte & 0X0F];

        String s = new String(tempArr);
        return s;
    }

	public static String getWxAppId() {
		return wxAppId;
	}

	public static void setWxAppId(String wxAppId) {
		Sh4Utils.wxAppId = wxAppId;
	}

	public static String getAppSecret() {
		return appSecret;
	}

	public static void setAppSecret(String appSecret) {
		Sh4Utils.appSecret = appSecret;
	}

	public static String getToken() {
		return token;
	}

	public static void setToken(String token) {
		Sh4Utils.token = token;
	}

	public static String getAccess_token() {
		
		//这里判断 若是access_token == null 或者 access_token_ctreate_date 过期 就重新请求 access_token 和重置 access_token_ctreate_date为当前时间
		if(Sh4Utils.access_token == null || Sh4Utils.access_token_ctreate_date == null) {
			refreshAccess_token();
			
		}else {
			Calendar c = Calendar.getInstance();
			c.setTime(access_token_ctreate_date);
			c.add(Calendar.SECOND, expires_in);
			
			if(System.currentTimeMillis() > c.getTimeInMillis()) {//判断时间是否超时 超时就刷新 access_token 否则 返回access_token
				refreshAccess_token();
			}
			
		}
		return access_token;
	}
	
	public static void refreshAccess_token() {
		JSONObject json =  Core.getServeAccessToken(Sh4Utils.getWxAppId(), Sh4Utils.getAppSecret());
		Sh4Utils.setAccess_token(json.getString("access_token"));
		Sh4Utils.setAccess_token_ctreate_date(new Date());
		Sh4Utils.expires_in = json.getInt("expires_in");
	}

	public static void setAccess_token(String access_token) {
		Sh4Utils.access_token = access_token;
	}

	public static Date getAccess_token_ctreate_date() {
		return access_token_ctreate_date;
	}

	public static void setAccess_token_ctreate_date(Date access_token_ctreate_date) {
		Sh4Utils.access_token_ctreate_date = access_token_ctreate_date;
	}

	public static String getRootUrl() {
		return rootUrl;
	}

	public static void setRootUrl(String rootUrl) {
		Sh4Utils.rootUrl = rootUrl;
	}
	
	
}
